package de.hdu.myjobapp.ctrl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;

import com.vaadin.data.Item;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.util.BeanItemContainer;

import de.hdu.myjobapp.dao.ApplicationDao;
import de.hdu.myjobapp.dao.OrganisationDao;
import de.hdu.myjobapp.dao.RatingDao;
import de.hdu.myjobapp.dao.StatusDao;
import de.hdu.myjobapp.dao.UserDao;
import de.hdu.myjobapp.model.Application;
import de.hdu.myjobapp.model.Organisation;
import de.hdu.myjobapp.model.Rating;
import de.hdu.myjobapp.model.Status;
import de.hdu.myjobapp.model.User;
import de.hdu.myjobapp.view.MyJobApplication;
/**
 * Load Data into Vaadin Specific Containers
 * Calculates Overall Rating
 * Has Methods to save data to Database
 * Methods to add and delete Ratings and States
 * @author MTA
 *
 */
public class ApplicationController {
	private static final long serialVersionUID = 1L;
	private transient Logger log = Logger.getLogger(ApplicationController.class);
	private BeanItemContainer<Application> applications = new BeanItemContainer<Application>(Application.class); 
	private BeanItemContainer<Status> states = new BeanItemContainer<Status>(Status.class); 
	private BeanItemContainer<Rating> ratings = new BeanItemContainer<Rating>(Rating.class); 
	private BeanItemContainer<Organisation> organisations = new BeanItemContainer<Organisation>(Organisation.class); 
	
	List<Rating> ratingsArray = new ArrayList<Rating>();

	private boolean dataLoadSwitchApplication = false;
	private boolean dataLoadSwitchRating = false;
	private boolean dataLoadSwitchStatus = false;
	
	//Spring BeanInjection of Applications
	private ApplicationDao applicationDao = null;
	public void setApplicationDao(ApplicationDao applicationDao){
		this.applicationDao = applicationDao;
	}
	//Spring BeanInjection of Applications
		private OrganisationDao organisationDao = null;
		public void setOrganisationDao(OrganisationDao organisationDao){
			this.organisationDao = organisationDao;
		}
	//Spring BeanInjection of Status
	private RatingDao ratingDao = null;
	public void setRatingDao(RatingDao ratingDao){
		this.ratingDao = ratingDao;
	}
	//Spring BeanInjection of Ratings
	private StatusDao statusDao = null;
	public void setStatusDao(StatusDao statusDao){
		this.statusDao = statusDao;
	}
	/**
	 * Default Constructor
	 */
	public ApplicationController(){
		
	}
	/**
	 * Internal Method to load the Applicationobjects from the Database in a 
	 * BeanItemContainer 
	 */
	private void loadApplications(){
		List<Application> applications = applicationDao.findAll((User)MyJobApplication.getProject().getUser());
		//List<Application> applications = applicationDao.finduserapplications();
		this.applications.removeAllItems();
		for(Application application:applications){
			this.applications.addBean(application);
		}
	}
	/**
	 * Internal Method to load the Status Objects relating to a specific Application
	 *  from the Database in a BeanItemContainer 
	 */
	private void loadStates(Application application){
		List<Status> states = statusDao.findAll(application);
		this.states.removeAllItems();
		//List<Application> applications = applicationDao.finduserapplications();
		for(Status status:states){
			this.states.addBean(status);
		}
	}
	/**
	 * Internal Method to load the Rating Objects relating to a specific Application
	 *  from the Database in a BeanItemContainer 
	 */
	private void loadRatings(Application application){
		ratingsArray = ratingDao.findAll(application);
		this.ratings.removeAllItems();
		//List<Application> applications = applicationDao.finduserapplications();
		for(Rating rating:ratingsArray){
			this.ratings.addBean(rating);
		}
	}
	/**
	 *  Public method to deliver a BeanItemContainer containing all Application Objects 
	 *  to the Components e.g. Table...
	 *  @param Boolean to announce if a reload from data is necessary or not 
	 */
	public BeanItemContainer<Application> getApplications(Boolean refresh){
			loadApplications();
			dataLoadSwitchApplication = true;
		return this.applications;
	}
	/**
	 *  Public method to deliver a BeanItemContainer containing all Status Objects 
	 *  to the Components e.g. Table...
	 *  @param Boolean to announce if a reload from data is necessary or not 
	 *  @param Application It is necessary to know to which Application the objects should be related to
	 */
	public BeanItemContainer<Status> getStates(Boolean refresh, Application application){
		if(refresh ||! dataLoadSwitchStatus ){
			loadStates(application);
			dataLoadSwitchStatus = true;
		}
		return this.states;
	}
	/**
	 *  Public method to deliver a BeanItemContainer containing all Rating Objects 
	 *  to the Components e.g. Table...
	 *  @param Boolean to announce if a reload from data is necessary or not 
	 *  @param Application It is necessary to know to which Application the objects should be related to
	 */
	public BeanItemContainer<Rating> getRatings(Boolean refresh, Application application){
		if(refresh ||! dataLoadSwitchRating ){
			loadRatings(application);
			dataLoadSwitchRating = true;
		}
		return this.ratings;
	}
	/**
	 * public method to save or modify an application
	 * @param The modified or new application object
	 * @return true or false if not successful
	 */
	public Boolean saveApplicationItem(Application application){
			try{
				applicationDao.save(application);
				return true;
			}catch(Exception e){
				return false;
			}
		
	}
	/**
	 * Public Method to delete Ratings from Database 
	 * @param Rating which is to be deleted
	 * @return
	 */
	public Boolean deleteRating(Rating rating){
		try{
			ratingDao.delete(rating);
			return true;
		}catch(Exception e){
			return false;
		}
	}
	/**
	 * Public Method to save a Rating Object
	 * @param Rating object to save
	 * @return returns true on success
	 */
	public Boolean saveRating(Rating rating){
		try{
			ratingDao.save(rating);
			return true;
		}catch(Exception e){
			return false;
		}
	}
	/**
	 * It has been decided that Status Entries cannot be deleted
	 * @param status
	 * @return
	 */
//	public Boolean deleteStatus(Status status){
//		try{
//			statusDao.delete(status);
//			return true;
//		}catch(Exception e){
//			return false;
//		}
//	}
	/**
	 * Public Method to call the DAO Layer for 
	 * persisting a Status Object
	 * @param status-object to persist
	 * @return Returns true if the operation was successful
	 */
	public Boolean saveStatus(Status status){
		try{
			statusDao.save(status);
			return true;
		}catch(Exception e){
			return false;
		}
	}
	/**
	 * Public Helpermethod gets from all Ratings 
	 * that are in the Table a sum in String format back
	 * @return Returns the Overall Rating Value (Ratings are summed up) as String
	 */
	public String CountRatings() {
		int output=0;
		for(Rating rating:ratingsArray){
			output += rating.getRatingGrad();
		}
		
		return String.valueOf(output);
	}
	/**
	 *  Public method to deliver a BeanItemContainer containing all Organisation Objects 
	 *  to the Components e.g. Table...
	 *  @param Boolean to announce if a reload from data is necessary or not 
	 *  @return Returns all Organisations in a BeanItemContainer Object
	 */
	public BeanItemContainer<Organisation> getOrganisations() {
		loadOrganisations();
		return this.organisations;
	}
	/**
	 * Internal Method to load the Organisation Objects 
	 *  from the Database in a BeanItemContainer 
	 */
	private void loadOrganisations() {
		List<Organisation> organisations = organisationDao.findAll();
		this.organisations.removeAllItems();
		//List<Application> applications = applicationDao.finduserapplications();
		for(Organisation organisation:organisations){
			this.organisations.addBean(organisation);
		}
	}
	
	
	
}
